﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.Services.Common;
using Microsoft.WindowsAzure.StorageClient;

namespace CPlase.Lists
{
    public abstract class ListProvider<TypeInfo, TypeItem>
            where TypeInfo : ListInformationEntity
            where TypeItem : NumeratableListItemEntity
    {

        protected TypeInfo ListInfo;

        public ListProvider(TableServiceContext Context, EntityQuery ListInfoQuery)
        {
            ListInfo = GetListInfo(Context, ListInfoQuery);
        }

        //abstract public TypeInfo GetInfo(TableServiceContext Context, EntityQuery ListInfoQuery);
        abstract protected TypeInfo CreateListInfo(EntityQuery ListInfoQuery);

        public TypeInfo GetListInfo(TableServiceContext Context, EntityQuery ListInfoQuery)
        {
            var ListInfo = EQ1G.GetEntity<TypeInfo>(Context, ListInfoQuery);
            if (ListInfo == null)
            {
                var FastContext = Azure.GetContext();
                ListInfo = CreateListInfo(ListInfoQuery);
                if (!EQ1G.SaveEntity<TypeInfo>(FastContext, ListInfoQuery, ListInfo))
                {
                    throw new Exception();
                }
                FastContext.SaveChanges();
            }
            return ListInfo;
        }


        public bool AddItem(TableServiceContext Context, EntityQuery ItemQuery /* ? */, NumeratableListItemEntity Item)
        {
            try
            {

                Item.PartitionKey = ItemQuery.PartitionKey;
                Item.RowKey = ItemQuery.RowKey;

                Item.ListID = ListInfo.Identificator;
                Item.Position = ListInfo.ItemsCount;

                ListInfo.CountEnumerator++;
                ListInfo.ItemsCount++;
                Context.UpdateObject(ListInfo);
                Context.AddObject(ItemQuery.TableName + ItemQuery.ShardNumber, Item);

                return true;
            }
            catch
            {
                return false;
            }
        }
        public List<TypeItem> GetAllList(TableServiceContext Context, String TbName, Int32 NumTable )
        {
            var Q = Context.CreateQuery<TypeItem>(TbName + NumTable);
            IQueryable<TypeItem> Items = null;
            Items =
                    (from p in Q
                     where p.PartitionKey == ListInfo.Identificator 
                     select p);
            if (Items == null) return null;

            var SelectedList = new List<TypeItem>();
            try
            {
                foreach (var Item in Items)
                {
                    SelectedList.Add(Item);
                }
            }
            catch { }
            return SelectedList;
        }
        public TypeItem GetItemByPid(TableServiceContext Context, EntityQuery ItemQuery)
        {
            var Q = Context.CreateQuery<TypeItem>(ItemQuery.TableName + ItemQuery.ShardNumber);
            TypeItem it = (from p in Q
                           where p.PartitionKey == ItemQuery.PartitionKey &&
                           p.RowKey == ItemQuery.RowKey
                           select p).First<TypeItem>();
            return it;
        }
        /*public List<TypeItem> GetListOff(TableServiceContext Context, EntityQuery ItemQuery, Int32 Offset)
        {
            var Q = Context.CreateQuery<TypeItem>(ItemQuery.GetTable());
            IQueryable<TypeItem> Items = null;
            Items =
                   (from p in Q
                    where p.PartitionKey == ItemQuery.PartitionKey &&
                          p.Position > Offset 
                    select p);
            var SelectedList = new List<TypeItem>();
            foreach (var Item in Items)
            {
                SelectedList.Add(Item);
            }
            return SelectedList;
        }*/

        public List<TypeItem> GetListOff(TableServiceContext Context, EntityQuery ItemQuery, Int32 Offset)
        {
            var Q = Context.CreateQuery<TypeItem>(ItemQuery.GetTable());
            IQueryable<TypeItem> Items = null;
            Items =
                   (from p in Q
                    where p.PartitionKey == ItemQuery.PartitionKey &&
                          p.Position > Offset
                    select p);
            var SelectedList = new List<TypeItem>();
            foreach (var Item in Items)
            {
                SelectedList.Add(Item);
            }
            return SelectedList;
        }

        public List<TypeItem> GetAllList(TableServiceContext Context, EntityQuery ItemQuery)
        {
            var Q = Context.CreateQuery<TypeItem>(ItemQuery.GetTable());
            IQueryable<TypeItem> Items = null;
            Items =
                   (from p in Q
                    where p.PartitionKey == ItemQuery.PartitionKey &&
                          p.ListID == ListInfo.Identificator 
                    select p);
            var SelectedList = new List<TypeItem>();
            foreach (var Item in Items)
            {
                SelectedList.Add(Item);
            }
            return SelectedList;
        }

        public List<TypeItem> GetList(TableServiceContext Context, EntityQuery ItemQuery, Int32 Offset, Int32 Limit, bool Asc = true)
        {
            var Q = Context.CreateQuery<TypeItem>(ItemQuery.GetTable());
            Int32 First = Offset;
            Int32 Last = Offset + Limit;
            IQueryable<TypeItem> Items = null;
            if (Asc)
            {
                Items =
                    (from p in Q
                     where p.PartitionKey == ItemQuery.PartitionKey &&
                           p.ListID == ListInfo.Identificator &&
                           p.Position >= First &&
                           p.Position < Last
                     select p);
            }
            else
            {
                First = ListInfo.ItemsCount - First;
                Last = First - Limit;
                if (First < 0) First = 0;
                if (Last < 0) Last = 0;
                
                Items =
                    (from p in Q
                     where p.PartitionKey == ItemQuery.PartitionKey &&
                           p.ListID == ListInfo.Identificator &&
                           p.Position < First &&
                           p.Position >= Last
                     select p);
            }

            if (Items == null) return null;

            var SelectedList = new List<TypeItem>();
            try
            {
                foreach (var Item in Items)
                {
                    SelectedList.Add(Item);
                }
            }
            catch { }
            SelectedList.Sort();
            if (!Asc) SelectedList.Reverse();

            return SelectedList;
        }

        /// <summary>
        /// TODO
        /// </summary>
        /// <returns></returns>
        public bool Delete(TableServiceContext Context, EntityQuery ItemQuery, NumeratableListItemEntity Item)
        {
            try
            {
                ListInfo.ItemsCount--;

               // Item.PartitionKey = ItemQuery.PartitionKey;
                //Item.RowKey = ItemQuery.RowKey;

                //Item.ListID = ListInfo.Identificator;
                //Item.Position = ListInfo.ItemsCount;

                
                Context.UpdateObject(ListInfo);
                Context.DeleteObject(Item);
                List<TypeItem> list = GetListOff(Context, ItemQuery, Item.Position);
                if (list != null)
                {
                    foreach (var item in list)
                    {
                        item.Position--;
                        Context.UpdateObject(item);
                    }
                }

                return true;
            }
            catch
            {
                return false;
            }
        }


        public bool DeleteAllList(TableServiceContext Context, EntityQuery ItemQuery)
        {
            try
            {
                
                List<TypeItem> list = GetAllList(Context, ItemQuery);
                if (list != null)
                {
                    foreach (var item in list)
                    {
    
                        Context.DeleteObject(item);
                    }
                }
                Context.DeleteObject(ListInfo);

                return true;
            }
            catch
            {
                return false;
            }
        }


        /// <summary>
        /// TODO
        /// </summary>
        /// <returns></returns>
        public TypeItem GetItemByPosition()
        {
            return null;
        }

        /*/
        public static List<Info, Item> GetList(TableServiceContext Context, EntityQuery ListEntityQuery)
        {
            var ListInfo = QueryUtils1G.GetEntity<Info>(Context, ListEntityQuery);
            if (ListInfo == null) return null;
            var List = new List<Info, Item>()
            {
                ListInfo = ListInfo
            };
            return List;
        }
        //*/

        public List<PagerItem> GetPages(Int32 ItemsPerPage)
        {
            return GetPages(ListInfo.ItemsCount, ItemsPerPage);
        }

        public static List<PagerItem> GetPages(Int64 TotlalItemsCount, Int32 ItemsPerPage)
        {
            var Pages = new Pages();
            Int32 PageNum = 0;
            for (int i = 0; i < TotlalItemsCount; i += ItemsPerPage)
            {
                PageNum++;
                Pages.Add(new PagerItem()
                {
                    PageNum = PageNum,
                    Offset = i
                });
            }
            return Pages;
        }

    }

    public class Pages : List<PagerItem> { };

    public class PagerItem
    {
        public Int32 PageNum;
        public Int32 Offset;
    }

}